import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:file_picker/file_picker.dart';
import 'package:dio/dio.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:video_player/video_player.dart';
import 'package:pornhub_app/components/diolog/dialog.dart';
import 'package:pornhub_app/http/api/api.dart';
import 'package:pornhub_app/http/http_service.dart';
import 'package:pornhub_app/model/community/publish_tags.dart';
import 'package:pornhub_app/utils/utils.dart';
import 'package:pornhub_app/utils/logger.dart';

class PostPublishVideoPageController extends GetxController {
  final contentText = ''.obs;
  final selectedType = Rxn<String>();
  final isAgreedToRules = false.obs;
  final TextEditingController textController = TextEditingController();
  final RxList<PublishTags> publishTagsList = <PublishTags>[].obs;
  final RxList<String> selectedTypes = <String>[].obs;
  final RxBool isLoading = false.obs;

  // 视频上传相关
  final Rx<File?> videoFile = Rx<File?>(null);
  final RxString uploadProgress = '0'.obs;
  final RxBool isUploading = false.obs;
  int finished = 0;
  CancelToken token = CancelToken();
  List<CancelToken> tokenList = List<CancelToken>.of([]);
  final chunkSize = 1 * 1024 * 1024;
  Map<String, dynamic>? uploadedVideoInfo;

  final Rx<File?> videoCover = Rx<File?>(null);

  final RxMap<String, dynamic> videoInfo = RxMap<String, dynamic>({
    'duration': 0,  // 视频时长(秒)
    'size': 0,      // 文件大小(字节)
    'width': 0,     // 视频宽度
    'height': 0,    // 视频高度
  });


  Future<void> updateVideoInfo(File videoFile) async {
    try {
      // 使用 video_player 或其他视频处理库获取视频信息
      final VideoPlayerController videoController = VideoPlayerController.file(videoFile);
      await videoController.initialize();

      videoInfo.value = {
        'duration': videoController.value.duration.inSeconds,
        'size': await videoFile.length(),
        'width': videoController.value.size.width.toInt(),
        'height': videoController.value.size.height.toInt(),
      };

      await videoController.dispose();
    } catch (e) {
      print('获取视频信息失败: $e');
    }
  }



  @override
  void onInit() {
    super.onInit();
    getPublishTags();
    textController.addListener(() {
      contentText.value = textController.text;
    });
  }

  @override
  void onClose() {
    textController.dispose();
    cancelAllUploads();
    super.onClose();
  }


  void removeVideo() {
    // 清除视频文件
    videoFile.value = null;

    // 清除视频封面
    videoCover.value = null;

    // 清除视频信息
    videoInfo.clear();

    // 清除已上传的视频信息
    uploadedVideoInfo = null;

    // 重置上传进度
    uploadProgress.value = '0';
    isUploading.value = false;

    // 取消所有正在进行的上传请求
    if (tokenList.isNotEmpty) {
      for (var token in tokenList) {
        token.cancel("用户移除视频");
      }
      tokenList.clear();
    }

    // 通知UI更新
    update();
  }


  void cancelAllUploads() {
    if (tokenList.isNotEmpty) {
      for (var token in tokenList) {
        token.cancel("exit page and cancel the request");
      }
      tokenList.clear();
    }
  }

  // 选择视频
  Future<void> pickVideo() async {
    if (!kIsWeb) {
      await Permission.storage.request();
      var status = await Permission.photos.request();
      if (!status.isGranted) {
        status = await Permission.storage.request();
      }
      if (!status.isGranted) return;
    }

    try {
      FilePickerResult? result = await FilePicker.platform.pickFiles(
        type: FileType.video,
      );

      if (result != null) {
        if (kIsWeb) {
          await videoSlice(result.files[0].bytes!, result.files[0].name);
        } else {
          File file = File(result.paths[0]!);
          videoFile.value = file;
          Uint8List videoBytes = await file.readAsBytes();
          await videoSlice(videoBytes, result.files[0].name);
        }
      }
    } catch (e) {
      showToast("选择视频失败: ${e.toString()}");
    }
  }

  // 视频分片上传
  Future<void> videoSlice(Uint8List bytes, String title) async {
    isUploading.value = true;
    finished = 0;

    try {
      var chunkNum = (bytes.length / chunkSize).ceil();
      int limit = 3;
      String taskId = Utils.md5String(title.split('.').first);
      List<int> list = List.generate(chunkNum, (idx) => idx);

      var count = 0;
      await Future.wait(list.map((item) async {
        while (count >= limit) {
          await Future.delayed(const Duration(milliseconds: 500));
        }
        count++;

        var chunk = (item == list.length - 1)
            ? bytes.sublist(item * chunkSize)
            : bytes.sublist(item * chunkSize, (item + 1) * chunkSize);

        try {
          var resp = await uploadVideoChunk(chunk, item, taskId);
          if (resp != null) {
            finished++;
            uploadProgress.value = (((finished) / chunkNum) * 100).toStringAsFixed(1);

            if (finished == chunkNum) {
              await completeVideoUpload(taskId, resp['id'], title);
            }
          }
        } catch (e) {
          await retryUploadChunk(chunk, item, taskId);
        } finally {
          count--;
        }
      }));
    } catch (e) {
      showToast("视频上传失败: ${e.toString()}");
    } finally {
      isUploading.value = false;
    }
  }

  Future<Map<String, dynamic>?> uploadVideoChunk(Uint8List chunk, int pos, String taskId) async {
    var token = CancelToken();
    tokenList.add(token);

    return await httpInstance.multiPartFormPost(
        url: "upload/video",
        isVideo: true,
        token: token,
        file: chunk,
        body: {
          "pos": pos,
          "taskId": taskId,
        }
    );
  }

  Future<void> retryUploadChunk(Uint8List chunk, int pos, String taskId) async {
    var resp = await uploadVideoChunk(chunk, pos, taskId);
    if (resp == null) {
      await retryUploadChunk(chunk, pos, taskId);
    } else {
      finished++;
    }
  }

  Future<void> completeVideoUpload(String taskId, String videoId, String title) async {
    await httpInstance.post(
        url: "upload/videoOk",
        isFile: true,
        body: {
          "checkSum": taskId,
          "id": videoId,
          "title": title,
          "type": 1,
        }
    );

    uploadProgress.value = '上传完成';
    uploadedVideoInfo = {
      "checkSum": taskId,
      "id": videoId,
      "playTime": 0,
      "uri": videoId, // 使用返回的视频URI
      'title': title
    };
  }

  // 发布视频内容
  Future<void> publishVideo() async {
    if (contentText.value.trim().isEmpty) {
      showToast("请输入视频描述");
      return;
    }

    if (getSelectedTagsInfo().isEmpty) {
      showToast("请选择发布类型");
      return;
    }

    if (!isAgreedToRules.value) {
      showToast("请同意发布规则");
      return;
    }

    if (uploadedVideoInfo == null) {
      showToast("请上传视频");
      return;
    }

    isLoading.value = true;
    try {
      final params = buildPublishParams(
        cityName: await getCityName(),
        content: contentText.value.trim(),
        coteries: getSelectedTagsInfo(),
        video: uploadedVideoInfo,
      );

      final response = await Api.publishRelease(params);

      if (response) {
        showToast("发布成功");
        clearAllData();
        Get.back(result: true);
      } else {
        showToast("发布失败");
      }
    } catch (e) {
      showToast("发布失败: ${e.toString()}");
    } finally {
      isLoading.value = false;
    }
  }

  // 其他辅助方法保持不变...
  void toggleType(String type) {
    if (selectedTypes.contains(type)) {
      selectedTypes.remove(type);
    } else {
      selectedTypes.add(type);
    }
  }

  bool isTypeSelected(String type) {
    return selectedTypes.contains(type);
  }

  void clearAllData() {
    contentText.value = '';
    textController.clear();
    selectedType.value = null;
    isAgreedToRules.value = false;
    videoFile.value = null;
    uploadedVideoInfo = null;
    uploadProgress.value = '0';
    selectedTypes.clear();
    update();
  }

  // 获取发布标签
  void getPublishTags() {
    isLoading.value = true;
    Api.getPublishTags().then((response) {
      if (response.isNotEmpty) {
        publishTagsList.value = (response as List<dynamic>)
            .map((item) => PublishTags.fromJson(item as Map<String, dynamic>))
            .toList();
        update();
      }
    }).catchError((error) {
      showToast("获取标签失败: ${error.toString()}");
    }).whenComplete(() {
      isLoading.value = false;
    });
  }

  List<Map<String, String>> getSelectedTagsInfo() {
    List<Map<String, String>> selectedTagsInfo = [];
    for (String tagName in selectedTypes) {
      final selectedTag = publishTagsList.firstWhere(
            (tag) => tag.name == tagName,
        orElse: () => PublishTags(id: '', name: ''),
      );
      if (selectedTag.id.isNotEmpty) {
        selectedTagsInfo.add({
          'id': selectedTag.id,
          'name': selectedTag.name,
        });
      }
    }
    return selectedTagsInfo;
  }

  Future<String> getCityName() async => '';

  void toggleAgreement() {
    isAgreedToRules.value = !isAgreedToRules.value;
  }

  Map<String, dynamic> buildPublishParams({
    required String cityName,
    required String content,
    List<Map<String, String>>? coteries,
    List<String>? dynamicImg,
    int gold = 0,
    Map<String, dynamic>? video,
  }) {
    return {
      'cityName': cityName,
      'content': content,
      'coteries': coteries ?? [],
      'dynamicImg': dynamicImg ?? [],
      'gold': gold,
      if (video != null) 'video': video,
    };
  }
}
